From 9b8830fe35ac9a2c2efabc1e91244e8abcd12345 Mon Sep 17 00:00:00 2001 From: Ayush Tiwari Date: Mon, 16 Mar 2026 12:00:00 +0000 Subject: [Draft Patch v1] Prevent SLRU divergence by checking wraparound before WAL flush In TruncateMultiXact(), if SimpleLruTruncate() encounters an apparent wraparound, it aborts the truncation safely. However, the TRUNCATE_ID WAL record has already been emitted. Standbys blindly replay this record and delete their SLRU segments. This patch outlines a structural reordering so we only emit the TRUNCATE WAL record if we are guaranteed to follow through. --- src/backend/access/transam/multixact.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index a1b2c3d4e..f5g6h7i8j 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -2980,10 +2980,20 @@ TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB) Assert((MyProc->delayChkptFlags & DELAY_CHKPT_START) == 0); MyProc->delayChkptFlags |= DELAY_CHKPT_START; - /* WAL log truncation */ - WriteMTruncateXlogRec(newOldestMultiDB, newOldestMulti, newOldestOffset); + /* + * TODO/DRAFT: + * We should check if SimpleLruTruncate() will abort due to + * apparent wraparound *before* flushing the WAL. + * + * if (SimpleLruCheckWraparound(MultiXactOffsetCtl, MultiXactIdToOffsetPage(newOldestMulti)) && + * SimpleLruCheckWraparound(MultiXactMemberCtl, MultiXactIdToMemberPage(newOldestOffset))) + * { + * // WAL log truncation + * WriteMTruncateXlogRec(newOldestMultiDB, newOldestMulti, newOldestOffset); + * // update in array limits, etc. + * // perform physical truncation + * } + */ /* * Update in-memory limits before performing the truncation, while inside -- 2.34.1